using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace _3DTicTacToe
{
    struct LogEntry
    {
        public DateTime Timestamp;
        public string[] Flags;
        public string Message;

        public LogEntry(string message)
            : this(message, new string[] { })
        {
        }

        public LogEntry(string message, params string[] flags)
        {
            Timestamp = DateTime.Now;
            Flags = flags;
            Message = message;
        }
    }

    static class Log
    {
        private static readonly List<LogEntry> Entries = new List<LogEntry>(512);

        public delegate void LogEntryDlg(LogEntry newEntry);
        public static event LogEntryDlg OnLogEntry;

        public static void Add(string message)
        {
            Add(message, new string[] {});
        }

        public static void Add(string message, params string[] flags)
        {
            var entry = new LogEntry(message, flags);
            Entries.Add(entry);

            if (OnLogEntry != null) OnLogEntry(entry);
        }

        public static void Add(LogEntry entry)
        {
            Entries.Add(entry);

            if (OnLogEntry != null) OnLogEntry(entry);
        }

        public static string GetString(LogEntry entry)
        {
            var str = "<" + entry.Timestamp.ToLongTimeString() + "."+ entry.Timestamp.Millisecond + "> ";
            if (entry.Flags.Length > 0)
                str += "[" + entry.Flags.Aggregate((n, m) => n + " " + m) + "] ";
            str += entry.Message;

            return str;
        }

        public static string GetLogString()
        {
            return GetLogString(Entries);
        }

        public static string GetLogString(IEnumerable<LogEntry> entries)
        {
            var sb = new StringBuilder();

            var lines = entries.Select(n => GetString(n));
            foreach (var line in lines)
                sb.AppendLine(line);

            return sb.ToString();
        }

        public static IEnumerable<LogEntry> Filter(params string[] flags)
        {
            return Entries.Where(n => n.Flags.All(s => flags.Contains(s)));
        }
    }
}